package cn.itcast.nems.studentrecord.service.impl;

import cn.hutool.core.lang.Assert;
import cn.itcast.ic.common.exception.v2.BizExceptionProducer;
import cn.itcast.nems.common.enumeration.NemsErrorBodyEnum;
import cn.itcast.nems.manager.util.CustomBeanUtil;
import cn.itcast.nems.studentrecord.dao.entity.StudentRecordLock;
import cn.itcast.nems.studentrecord.dao.mapper.StudentRecordLockMapper;
import cn.itcast.nems.studentrecord.dto.StudentRecordLockDTO;
import cn.itcast.nems.studentrecord.enumeration.StudentRecordErrorBodyEnum;
import cn.itcast.nems.studentrecord.service.StudentRecordLockService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 学籍锁详情 服务实现类
 * </p>
 *
 * @author 刘曙
 * @since 2024-01-18
 */
@Service
@Slf4j
public class StudentRecordLockServiceImpl extends ServiceImpl<StudentRecordLockMapper, StudentRecordLock> implements StudentRecordLockService {

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void lock(@NonNull StudentRecordLockDTO lockDTO) {
        Assert.notNull(lockDTO.getReferenceId(), BizExceptionProducer.produce(NemsErrorBodyEnum.PARAM_EMPTY, "学籍锁详情凭单ID"));
        Assert.notNull(lockDTO.getReferenceType(), BizExceptionProducer.produce(NemsErrorBodyEnum.PARAM_EMPTY, "学籍锁详情凭单类型"));
        this.update(lockDTO, true);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void unlock(@NonNull StudentRecordLockDTO lockDTO) {
        this.update(lockDTO ,false );
    }


    private void update(StudentRecordLockDTO lockDTO , Boolean lockFlag) {
        List<StudentRecordLock> studentRecordLocks = getBaseMapper().selectList(
                        new LambdaQueryWrapper<StudentRecordLock>()
                                .eq(StudentRecordLock::getStudentRecordId, lockDTO.getStudentRecordId())
                                .eq(Objects.nonNull(lockDTO.getReferenceId()),StudentRecordLock::getReferenceId, lockDTO.getReferenceId())
                                .eq(Objects.nonNull(lockDTO.getReferenceType()),StudentRecordLock::getReferenceType, lockDTO.getReferenceType())
                                .eq(StudentRecordLock::getState , !lockFlag)
                                .eq(StudentRecordLock::getDeletedFlag ,false)
        );
        // 存在多条学籍锁记录
        log.info("【维护学籍锁记录】查询条件：{} ,lockFlag：{}, 查询结果：{}",
                JSON.toJSONString(lockDTO), lockFlag,
                JSON.toJSONString(studentRecordLocks, SerializerFeature.DisableCircularReferenceDetect)
        );
        Assert.isFalse(CollectionUtils.isNotEmpty(studentRecordLocks) && studentRecordLocks.size() > 1,
                BizExceptionProducer.produce(StudentRecordErrorBodyEnum.STUDENT_RECORD_LOCK_DATA_NOT_ONE, lockDTO.getStudentRecordId()));

        if (CollectionUtils.isNotEmpty(studentRecordLocks)) {
            studentRecordLocks.forEach(item -> {
                if (item.getState() ^ lockFlag) {
                    int updateResult = getBaseMapper().update(null,
                            new LambdaUpdateWrapper<StudentRecordLock>()
                                    .set(StudentRecordLock::getState, lockFlag)
                                    .eq(StudentRecordLock::getId, item.getId())
                    );
                    Assert.isTrue(updateResult > 0,
                            BizExceptionProducer.produce(NemsErrorBodyEnum.DATABASE_UPDATE_ERROR, "学籍锁详情"));
                }
            });
            return;
        }
        // 如果 lockFlag 为真 ， 代表需要添加锁记录
        if (lockFlag) {
            StudentRecordLock studentRecordLock = CustomBeanUtil.copyProperties(lockDTO, new StudentRecordLock());
            studentRecordLock.setState(lockFlag);
            boolean insertFlag = this.saveOrUpdate(studentRecordLock);
            Assert.isTrue(insertFlag,
                    BizExceptionProducer.produce(NemsErrorBodyEnum.DATABASE_INSERT_ERROR, "学籍锁详情"));
        }
    }
}
